﻿using System;
using System.Collections.Generic;
using System.Reflection;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Zove.Runtime.Core.Zoom;
using Zove.Runtime.Queries;
using EmbeddedSharp.Core;
using EmbeddedSharp.Core.Function.Trigonometry;

namespace Zove.Runtime.Test {
    [TestClass]
    public class QueryTests {
        [TestMethod]
        public void TestParse() {
            var p = new QueryParser(new ZoomLanguageNature());
            Query d = p.Parse("select hello, kitty from world where name='me', addr='java';");

            Console.WriteLine(d.ToString());
        }

        [TestMethod]
        public void TestConvert()
        {
            SinNode node = new SinNode();
            Type type = node.GetType();
            object obj = type.Assembly.CreateInstance(type.FullName);
            FuncNode n = obj as FuncNode;

            Assembly assembly = Assembly.LoadFrom(
                @"D:\Projects\zove-2010\Zove\Zove.Runtime.Test\bin\Debug\EmbeddedSharp.Core.dll"
//@"C:\Users\Administrator\Documents\Visual Studio 2008\Projects\Zove\Zove.Runtime.Test\bin\Debug\EmbeddedSharp.Core.dll"
);
            type = assembly.GetType("EmbeddedSharp.Core.Function.Trigonometry.SinNode");

            obj = assembly.CreateInstance(type.FullName);
            n = (FuncNode)obj;
            n.Evaluate();
        }

        public Dictionary<string, QueryResult> Query(string query) {
            var qm = new QueryManager(new ZoomLanguageNature());
            Query q = qm.CreateQuery(query);
            Dictionary<string, QueryResult> results = q.Run();

            return results;
        }

        [TestMethod]
        public void TestCircle() {
            Dictionary<string, QueryResult> results = Query(
                "select * from circle where r=10;");

            Assert.AreEqual("area", results["area"].Item);
            Assert.AreEqual("314.15926", results["area"].Value);

            DisplayResults(results);
        }

        [TestMethod]
        public void TestBooleanQuery() {
            Dictionary<string, QueryResult> results = Query(
                "select area > 0 from circle where r=10;");

            Assert.AreEqual("area>0", results["area>0"].Item);
            Assert.AreEqual("True", results["area>0"].Value);
        }

        [TestMethod]
        public void TestEllipse() {
            Dictionary<string, QueryResult> results = Query(
                "select * from ellipse where c=10;");

            //Assert.AreEqual("area", results[0].Item);
            //Assert.AreEqual("282.743334", results[0].Value);

            DisplayResults(results);
        }

        [TestMethod]
        public void TestTrapzoid() {
            Dictionary<string, QueryResult> results = Query(
                "select area from trapezoid where top=5, bottom=9, height=10, A=3.14/3, B=3.14/6;");

            Assert.AreEqual("area", results["area"].Item);
            Assert.AreEqual("70", results["area"].Value);
        }

        [TestMethod]
        public void TestCone() {
            Dictionary<string, QueryResult> results = Query(
                "select * from cone where height=9, bottom.c=10;");

            DisplayResults(results);
        }

        [TestMethod]
        public void TestCylinder() {
            Dictionary<string, QueryResult> results = Query(
                "select * from cylinder where height=9, bottom.c=10;");

            DisplayResults(results);
        }

        public void DisplayResults(Dictionary<string, QueryResult> results) {
            foreach (QueryResult result in results.Values) {
                Console.WriteLine(@"{0} = {1}", result.Item, result.Value);
            }
        }

        [TestMethod]
        public void TestPlanar() {
            const string source = @"select * from circle where r=5;
select * from triangle where a=3,b=4,c=5;
select * from square where edge=5;
select * from rectangle where width=5, height=7;
select * from ellipse where a=4,b=5;
select * from trapezoid where top=5, bottom=7, A=3.14/5, B=3.14/8;
select * from quadrilateral where a=2,b=3,c=4,d=5;
select * from rhombus where a=3,A=3.14/6;";

            Dictionary<string, QueryResult> results = Query(source);
            foreach(string key in results.Keys)
            {
                Console.WriteLine(results[key].Value);
            }
        }

        [TestMethod]
        public void TestSpatial() {
            const string source =
                @"# polyhedra
select * from tetrahedron where e1=1,e2=1,e3=1,e4=1,e5=1,e6=1;
select * from regulartetrahedron where edge=1,bottomEdge=1,slantHeight=1;

# conical frustums
select * from conicalfrustum where top.r=5,bottom.r=10,height=7;
select * from cone where height=7,bottom.c=10;
select * from cylinder where bottom.r=5,height=10;

# prisms
assert area=6 from cube where edge=1;
select * from prism;
select * from cuboid;

# sphere
select * from sphere where r=10;
select * from SphericalCap where height=10,volume=100;
select * from zone where height=10,volume=100;

# cuboid
select * from box where height=10;";

            Dictionary<string, QueryResult> results = Query(source);

            foreach (QueryResult result in results.Values) {
                Console.WriteLine(result.ToString());
            }
        }

        [TestMethod]
        public void TestSphereCone() {
            Dictionary<string, QueryResult> list = Query("select volume from spherecone where r=10, alpha=3.14/6;");

            DisplayResults(list);
        }
    }
}